package com.md2ppt.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * JSON配置文件解析器
 * 使用Jackson ObjectMapper解析配置
 */
public class ConfigParser {
    
    private static final Logger logger = LoggerFactory.getLogger(ConfigParser.class);
    private final ObjectMapper objectMapper;
    
    public ConfigParser() {
        this.objectMapper = new ObjectMapper();
    }
    
    /**
     * 从文件解析配置
     */
    public PresentationConfig parseFromFile(Path configPath) throws IOException {
        logger.debug("解析配置文件: {}", configPath);
        
        if (!Files.exists(configPath)) {
            throw new IOException("配置文件不存在: " + configPath);
        }
        
        var jsonContent = Files.readString(configPath);
        return parseFromJson(jsonContent);
    }
    
    /**
     * 从JSON字符串解析配置
     */
    public PresentationConfig parseFromJson(String jsonContent) throws IOException {
        try {
            // 验证JSON格式
            var jsonNode = objectMapper.readTree(jsonContent);
            validateConfigStructure(jsonNode);
            
            // 解析为配置对象
            var config = objectMapper.readValue(jsonContent, PresentationConfig.class);
            
            // 验证配置内容
            validateConfigContent(config);
            
            logger.info("配置解析成功，包含 {} 张幻灯片", config.slides().size());
            return config;
            
        } catch (Exception e) {
            logger.error("配置解析失败", e);
            throw new IOException("配置解析失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 验证JSON结构
     */
    private void validateConfigStructure(JsonNode rootNode) throws IOException {
        var requiredFields = new String[]{"metadata", "settings", "slides"};
        
        for (var field : requiredFields) {
            if (!rootNode.has(field)) {
                throw new IOException("缺少必需字段: " + field);
            }
        }
        
        // 验证slides是数组
        if (!rootNode.get("slides").isArray()) {
            throw new IOException("slides字段必须是数组");
        }
        
        // 验证至少有一张幻灯片
        if (rootNode.get("slides").size() == 0) {
            throw new IOException("必须至少包含一张幻灯片");
        }
    }
    
    /**
     * 验证配置内容
     */
    private void validateConfigContent(PresentationConfig config) throws IOException {
        // 验证元数据
        if (config.metadata().title() == null || config.metadata().title().trim().isEmpty()) {
            throw new IOException("演示文稿标题不能为空");
        }
        
        // 验证设置
        var settings = config.settings();
        if (settings.animationEngine() == null) {
            throw new IOException("必须指定动画引擎");
        }
        
        // 验证动画引擎类型
        var validEngines = new String[]{"ASPOSE_JAVA", "PYTHON_PPTX", "REVEAL_JS"};
        var engineValid = false;
        for (var engine : validEngines) {
            if (engine.equals(settings.animationEngine())) {
                engineValid = true;
                break;
            }
        }
        if (!engineValid) {
            throw new IOException("不支持的动画引擎: " + settings.animationEngine());
        }
        
        // 验证幻灯片配置
        for (var slide : config.slides()) {
            validateSlideConfig(slide);
        }
    }
    
    /**
     * 验证单张幻灯片配置
     */
    private void validateSlideConfig(PresentationConfig.SlideConfig slide) throws IOException {
        if (slide.title() == null || slide.title().trim().isEmpty()) {
            throw new IOException("幻灯片 " + slide.index() + " 标题不能为空");
        }
        
        if (slide.content() == null || slide.content().isEmpty()) {
            logger.warn("幻灯片 {} 没有内容元素", slide.index());
        }
        
        // 验证动画配置
        if (slide.animations() != null) {
            for (var animation : slide.animations()) {
                validateAnimationConfig(animation, slide.index());
            }
        }
    }
    
    /**
     * 验证动画配置
     */
    private void validateAnimationConfig(PresentationConfig.AnimationConfig animation, int slideIndex) throws IOException {
        if (animation.targetElement() == null || animation.targetElement().trim().isEmpty()) {
            throw new IOException("幻灯片 " + slideIndex + " 动画目标元素不能为空");
        }
        
        if (animation.effectType() == null || animation.effectType().trim().isEmpty()) {
            throw new IOException("幻灯片 " + slideIndex + " 动画效果类型不能为空");
        }
        
        var timing = animation.timing();
        if (timing != null) {
            if (timing.duration() <= 0) {
                throw new IOException("幻灯片 " + slideIndex + " 动画持续时间必须大于0");
            }
            if (timing.startDelay() < 0) {
                throw new IOException("幻灯片 " + slideIndex + " 动画延迟时间不能为负数");
            }
        }
    }
}